﻿using System;
using System.Linq;

using Buddy.BehaviorTree;
using Buddy.CommonBot;
using Buddy.Swtor;
using Buddy.Swtor.Objects;

using WingIt;
using WingIt.Dynamics;
using WingIt.Routines.Mirrors;

namespace WingIt.Routines
{
    [RevisionControlId("$Id: WarriorKnightBasic.cs 686 2012-08-12 16:12:20Z Chinajade $")]
    public class WarriorKnight : MirrorRoutine
    {
        // MAINTAINERS NOTES:
        // * You will notice that lambda expression argument names are unique (e.g., "darkWardOn", "darkWardWhen", "joltWhen"),
        //   instead of generic (e.g., "ctx", "ret", "on", "doWhen", "castWhen").  PLEASE honor this convention!
        //   This allows us to quickly localize problems when looking at user's logs.  When the BehaviorTree encounters an exception
        //   (e.g., "object not found"), the location where an exception is thrown is identifiable only through the name
        //   of the lambda expression argument.  Such is the nature of BehaviorTrees.

        #region Convenience methods
        private static float    EngagementRange(TorCharacter target)    { return (RangeAbilityReady(target) ? Global.Distance.Ranged : Global.Distance.Melee); }
        private static bool     RangeAbilityReady(TorCharacter target)  { return (!target.IsCoverAffected &&
                                                                                  target.IsInRange(3f, 1f) &&
                                                                                  Me.IsMirrorAbilityReady("Force Charge", target)); }
        #endregion

        [Behavior(BehaviorType.Pull)]
        [Class(CharacterClass.Warrior)]
        [Class(CharacterClass.Warrior, AdvancedClass.Juggernaut, SkillTreeId.None)]
        [Class(CharacterClass.Warrior, AdvancedClass.Marauder, SkillTreeId.None)]
        [Class(CharacterClass.Knight)]
        [Class(CharacterClass.Knight, AdvancedClass.Guardian, SkillTreeId.None)]
        [Class(CharacterClass.Knight, AdvancedClass.Sentinel, SkillTreeId.None)]
        public static Composite WarriorKnight_Pull()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                CreateBTPS.BWcoreFixup_WaitForHarvestComplete(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                WarriorKnight_Combat()
                );
        }

        [Behavior(BehaviorType.Combat)]
        [Class(CharacterClass.Warrior)]
        [Class(CharacterClass.Warrior, AdvancedClass.Juggernaut, SkillTreeId.None)]
        [Class(CharacterClass.Warrior, AdvancedClass.Marauder, SkillTreeId.None)]
        [Class(CharacterClass.Knight)]
        [Class(CharacterClass.Knight, AdvancedClass.Guardian, SkillTreeId.None)]
        [Class(CharacterClass.Knight, AdvancedClass.Sentinel, SkillTreeId.None)]
        public static Composite WarriorKnight_Combat()
        {
            //Neo93 29.04.2012
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                // If we can jump a target, move to within jump range; otherwise move to melee range...
                Cast("Force Charge"), //+3 Rage/15s CD/30m Range - Pull
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, range => EngagementRange(MyTarget)),
                CreateBTPS.StopWithinRangeAndLoS(target => MyTarget, Global.Distance.Melee),

                //***General***
                Cast("Unleash", unleashWhen => Me.IsStunned),//Insignia/2m CD

                //**Defensive**
                BuffSelf("Saber Ward", saberWardWhen => Me.HealthPercent <= 50),//3m CD

                //**Offensive**
                Cast("Force Scream"),//-4Rage/2s CD
                Cast("Smash", smashWhen => Me.MobCountAround(Global.Distance.MeleeAoE) >= 3),//-3 Rage/15s CD
                Cast("Ravage"),//0 Rage/27s CD
                Cast("Retaliation"),//-3 Rage
                Cast("Vicious Slash"),//-3 Rage
                Cast("Assault")//+2 Rage
                );
        }

        [Behavior(BehaviorType.OutOfCombat)]
        [Class(CharacterClass.Warrior)]
        [Class(CharacterClass.Warrior, AdvancedClass.Juggernaut, SkillTreeId.None)]
        [Class(CharacterClass.Warrior, AdvancedClass.Marauder, SkillTreeId.None)]
        [Class(CharacterClass.Knight)]
        [Class(CharacterClass.Knight, AdvancedClass.Guardian, SkillTreeId.None)]
        [Class(CharacterClass.Knight, AdvancedClass.Sentinel, SkillTreeId.None)]
        public static Composite WarriorKnight_OutOfCombat()
        {
            // NB: Apparently, BWcore will call this routine when in combat on occasion.  It is also called while we're pulling.
            return (new PrioritySelector(
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),
                new Decorator(oocBuffWhen => !Me.IsMounted,
                    new PrioritySelector(
                        BuffSelf("Shii-Cho Form")
                        ))
                ));
        }
    }
}